package com.zzyl.nursing.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zzyl.common.exception.ServiceException;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.nursing.domain.CheckInConfig;
import com.zzyl.nursing.domain.Contract;
import com.zzyl.nursing.domain.Elder;
import com.zzyl.nursing.dto.CheckInApplyDto;
import com.zzyl.nursing.dto.CheckInElderDto;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import com.zzyl.utils.CodeGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.domain.CheckIn;
import com.zzyl.nursing.service.ICheckInService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;

/**
 * 入住Service业务层处理
 * 
 * @author laoYe
 * @date 2025-10-21
 */
@Slf4j
@Service
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService {
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private BedMapper bedMapper;

    /**
     * 查询入住
     * 
     * @param id 入住主键
     * @return 入住
     */
    @Override
    public CheckIn selectCheckInById(Long id) {
        return getById(id);
    }

    /**
     * 查询入住列表
     * 
     * @param checkIn 入住
     * @return 入住
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn) {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn) {
        return save(checkIn) ? 1 : 0;
    }

    /**
     * 修改入住
     * 
     * @param checkIn 入住
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn) {
        return updateById(checkIn) ? 1 : 0;
    }

    /**
     * 批量删除入住
     * 
     * @param ids 需要删除的入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids) {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除入住信息
     * 
     * @param id 入住主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id) {
        return removeById(id) ? 1 : 0;
    }

    /**
     * 入住申请
     * @param checkInApplyDto
     */
    @Transactional
    @Override
    public void apply(CheckInApplyDto checkInApplyDto) {
        //TODO 入住办理
        //1,保存老人信息checkin
        //2.老人是否存在,存在则更新
        //通过身份证号进行查询(为什么这里要用到elderMapper)
        CheckInElderDto checkInElderDto = checkInApplyDto.getCheckInElderDto();
        Elder elder = elderMapper.selectOne(new LambdaQueryWrapper<Elder>().eq(Elder::getIdCardNo, checkInApplyDto.getCheckInElderDto().getIdCardNo()));
        //判断老人是否已经入住
        if (elder != null) {
            if (elder.getStatus()>=2 && elder.getStatus() <= 4) {
                throw new ServiceException("该老人已入住");
            }
        }
        //老人没入住
        //checkinconfig中的床位id去查询床位的编号
        //更新床位的状态,更新结果,通过受影响的记录,如果受影响记录数>0则表示更新成功,乐观锁判定,利用数据库的行锁
        int rows = bedMapper.updateBedStatus(checkInApplyDto.getCheckInConfigDto().getBedId());
        if (rows == 0) {//利用数据库的行级锁进行判断
            //床位已有人
            throw new ServiceException("该床位已有人,请选择其它床");
        }
        //不存在则新增老人
        Elder newElder = saveOrUpdateElder(checkInApplyDto, elder);
        //保存入住信息
        CheckIn checkIn = addCheckIn(checkInApplyDto, newElder);
        // 添加入住合同信息
        addContract(checkInApplyDto,checkIn);
        // 添加入住配置信息
        addCheckConfig(checkInApplyDto,checkIn);

    }

    @Override
    public CheckInDetailVo detail(Long id) {
        // 1. 查询入住主表
        CheckIn checkIn = checkInMapper.selectById(id);
        if (checkIn == null) {
            return null;
        }

        CheckInDetailVo detailVo = new CheckInDetailVo();

        // 2. 查询老人信息
        Elder elder = elderMapper.selectById(checkIn.getElderId());
        if (elder != null) {
            CheckInElderVo elderVo = new CheckInElderVo();
            BeanUtil.copyProperties(elder, elderVo);

            // 处理生日和年龄（birthday 是 String）
            if (StrUtil.isNotBlank(elder.getBirthday())) {
                try {
                    LocalDateTime birthDateTime = DateUtil.parse(elder.getBirthday()).toLocalDateTime();
                    LocalDate birthDate = birthDateTime.toLocalDate();
                    int age = Period.between(birthDate, LocalDate.now()).getYears();
                    elderVo.setAge(age);
                    elderVo.setBirthday(elder.getBirthday());
                } catch (Exception e) {
                    log.warn("解析出生日期失败：{}", elder.getBirthday(), e);
                }
            } else {
                elderVo.setAge(null);
                elderVo.setBirthday(null);
            }

            detailVo.setCheckInElderVo(elderVo);
        }

        // 3. 解析家属信息（remark 字段）
        List<ElderFamilyVo> familyList = new ArrayList<>();
        if (StrUtil.isNotBlank(checkIn.getRemark())) {
            try {
                familyList = JSONUtil.toList(checkIn.getRemark(), ElderFamilyVo.class);
            } catch (Exception e) {
                log.warn("解析家属信息失败，入住ID：{}", id, e);
            }
        }
        detailVo.setElderFamilyVoList(familyList);

        // 4. 查询入住配置
        CheckInConfig config = checkInConfigMapper.selectOne(
                new LambdaQueryWrapper<CheckInConfig>().eq(CheckInConfig::getCheckInId, id)
        );
        if (config != null) {
            CheckInConfigVo configVo = new CheckInConfigVo();
            BeanUtil.copyProperties(config, configVo);
            configVo.setBedNumber(checkIn.getBedNumber()); // 补充床位号
            detailVo.setCheckInConfigVo(configVo);
        }

        // 5. 查询合同
        Contract contract = contractMapper.selectOne(
                new LambdaQueryWrapper<Contract>().eq(Contract::getCheckInId, id)
        );
        detailVo.setContract(contract);

        return detailVo;
    }

    @Autowired
    private CheckInConfigMapper checkInConfigMapper;
    /**
     * 添加入住配置信息
     * @param checkInApplyDto
     * @param checkIn
     */
    private void addCheckConfig(CheckInApplyDto checkInApplyDto, CheckIn checkIn) {
        CheckInConfig config =BeanUtil.toBean(checkInApplyDto.getCheckInConfigDto(), CheckInConfig.class);
        config.setCheckInId(checkIn.getId());
        config.setCreateTime(new Date());
        config.setUpdateTime(checkIn.getCreateTime());

        checkInConfigMapper.insert(config);

    }

    @Autowired
    private ContractMapper contractMapper;

    /**
     * 添加入住合同信息
     * @param checkInApplyDto
     * @param checkIn
     */
    private void addContract(CheckInApplyDto checkInApplyDto, CheckIn checkIn) {
        Contract contract =BeanUtil.toBean(checkInApplyDto.getCheckInContractDto(), Contract.class);
        contract.setCheckInId(checkIn.getId());
        contract.setElderId(checkIn.getElderId());
        String contractNumber =CodeGenerator.generateContractNumber();
        contract.setContractNumber(contractNumber);
        contract.setElderName(checkIn.getElderName());
        contract.setStartDate(checkIn.getStartDate());
        contract.setEndDate(checkIn.getEndDate());
        contract.setStatus(0);
        contract.setCreateTime(new Date());
        contract.setUpdateTime(contract.getCreateTime());
        contractMapper.insert(contract);

    }

    /**
     * 添加入住信息
     * @param checkInApplyDto
     * @param newElder
     */
    private CheckIn addCheckIn(CheckInApplyDto checkInApplyDto, Elder newElder) {
        CheckIn checkIn = new CheckIn();
        //老人信息表
        checkIn.setElderId(newElder.getId());
        checkIn.setElderName(newElder.getName());
        checkIn.setIdCardNo(newElder.getIdCardNo());
        checkIn.setStartDate(checkInApplyDto.getCheckInConfigDto().getStartDate());
        checkIn.setEndDate(checkInApplyDto.getCheckInConfigDto().getEndDate());
        checkIn.setNursingLevelName(checkInApplyDto.getCheckInConfigDto().getNursingLevelName());

        //床位
        checkIn.setBedNumber(newElder.getBedNumber());
        checkIn.setStatus(0);
        checkIn.setCreateTime(new Date());
        checkIn.setUpdateTime(checkIn.getCreateTime());

        //remark,老人的家属联系人,转成json字符串
        String jsonStr = JSONUtil.toJsonStr(checkInApplyDto.getElderFamilyDtoList());
        checkIn.setRemark(jsonStr);


        save(checkIn);//要使用mp的方法
        return checkIn;

    }

    /**
     * 保存老人信息
     * @param checkInApplyDto
     * @param elder
     */
    private Elder saveOrUpdateElder(CheckInApplyDto checkInApplyDto, Elder elder) {

        CheckInElderDto checkInElderDto = checkInApplyDto.getCheckInElderDto();
        Elder newElder = BeanUtil.toBean(checkInElderDto, Elder.class);
        //要设置新的床位编号
        //获取床位编号bed_number,通过id查询
        //床位的id
        long bedId = checkInApplyDto.getCheckInConfigDto().getBedId();
        newElder.setBedNumber(bedMapper.selectBedById(bedId).getBedNumber());
        newElder.setBedId(bedId);
        //状态
        newElder.setStatus(1);
        //判断老人是否存在
        if (elder != null) {
            //更新
            //更新时间
            newElder.setUpdateTime(new Date());
            newElder.setId(elder.getId());
            elderMapper.updateById(newElder);
        }else{
            //新增
            newElder.setCreateTime(new Date());
            elderMapper.insert(newElder);//要使用MP的方法,自动填充id
        }
        return newElder;
    }
}
